// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.IO.Pipelines;
using System.Reflection;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing;
using Moq;
using Xunit.Abstractions;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
    public class Http1ConnectionTestsBase : LoggedTest, IDisposable
    {
        internal IDuplexPipe _transport;
        internal IDuplexPipe _application;
        internal TestHttp1Connection _http1Connection;
        internal ServiceContext _serviceContext;
        internal HttpConnectionContext _http1ConnectionContext;
        internal MemoryPool<byte> _pipelineFactory;
        internal SequencePosition _consumed;
        internal SequencePosition _examined;
        internal Mock<ITimeoutControl> _timeoutControl;

        public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
        {
            base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper);

            _pipelineFactory = PinnedBlockMemoryPoolFactory.Create();
            var options = new PipeOptions(_pipelineFactory, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
            var pair = DuplexPipe.CreateConnectionPair(options, options);

            _transport = pair.Transport;
            _application = pair.Application;

            var connectionFeatures = new FeatureCollection();
            connectionFeatures.Set(Mock.Of<IConnectionLifetimeFeature>());

            _serviceContext = new TestServiceContext(LoggerFactory)
            {
                Scheduler = PipeScheduler.Inline
            };

            _timeoutControl = new Mock<ITimeoutControl>();
            _http1ConnectionContext = TestContextFactory.CreateHttpConnectionContext(
                serviceContext: _serviceContext,
                connectionContext: Mock.Of<ConnectionContext>(),
                transport: pair.Transport,
                timeoutControl: _timeoutControl.Object,
                memoryPool: _pipelineFactory,
                connectionFeatures: connectionFeatures);

            _http1Connection = new TestHttp1Connection(_http1ConnectionContext);
        }

        void IDisposable.Dispose()
        {
            base.Dispose();

            _transport.Input.Complete();
            _transport.Output.Complete();

            _application.Input.Complete();
            _application.Output.Complete();

            _pipelineFactory.Dispose();
        }
    }
}
